//
//  ALAssetsLibrary category to handle a custom photo album
//
//  Created by Marin Todorov on 10/26/11.
//  Copyright (c) 2011 Marin Todorov. All rights reserved.
//

#import <ImageIO/ImageIO.h>
#import "ALAssetsLibrary+CustomPhotoAlbum.h"

@implementation ALAssetsLibrary(CustomPhotoAlbum)

- (void)saveImage:(UIImage*)image toAlbum:(NSString*)albumName withMetaData:(NSDictionary *)metaData withCompletionBlock:(SaveImageCompletionExternal)completionBlock
{
    [self saveImage:image
        orientation:image.imageOrientation
            toAlbum:albumName
       withMetaData:metaData
         completion:completionBlock];
}

- (void)saveImage:(UIImage*)image
     orientation:(UIImageOrientation)srcOrientation
         toAlbum:(NSString*)albumName
    withMetaData:(NSDictionary *)metaData
      completion:(SaveImageCompletionExternal)completionBlock
{
    int orientation;
    switch (srcOrientation) {
        case UIImageOrientationUp:
            orientation = 1;
            break;
        case UIImageOrientationDown:
            orientation = 3;
            break;
        case UIImageOrientationLeft:
            orientation = 8;
            break;
        case UIImageOrientationRight:
            orientation = 6;
            break;
        case UIImageOrientationUpMirrored:
            orientation = 2;
            break;
        case UIImageOrientationDownMirrored:
            orientation = 4;
            break;
        case UIImageOrientationLeftMirrored:
            orientation = 5;
            break;
        case UIImageOrientationRightMirrored:
            orientation = 7;
            break;
        default:
            orientation = 1;
            break;
    }
    NSMutableDictionary *mutableMetaData = [NSMutableDictionary dictionaryWithDictionary:metaData];
    [mutableMetaData setObject:[NSNumber numberWithInt:orientation] forKey:(NSString *)kCGImagePropertyOrientation];
    metaData = [NSDictionary dictionaryWithDictionary:mutableMetaData];
    
    //write the image data to the assets library (camera roll)
    [self writeImageToSavedPhotosAlbum:image.CGImage
                              metadata:metaData
                       completionBlock:^(NSURL* assetURL, NSError* error) {
                           
                           //error handling
                           if (error!=nil) {
                               completionBlock(nil, error);
                               return;
                           }
                           
                           //add the asset to the custom photo album
                           if ([albumName length]) {
                               [self addAssetURL:assetURL
                                         toAlbum:albumName
                             withCompletionBlock:completionBlock];
                           } else {
                               completionBlock(assetURL, error);
                           }
                       }];
}


- (void)addAssetURL:(NSURL*)assetURL toAlbum:(NSString*)albumName withCompletionBlock:(SaveImageCompletionExternal)completionBlock
{
    __block BOOL albumWasFound = NO;
    
    //search all photo albums in the library
    [self enumerateGroupsWithTypes:ALAssetsGroupAlbum 
                        usingBlock:^(ALAssetsGroup *group, BOOL *stop) {

                            //compare the names of the albums
                            if ([albumName compare: [group valueForProperty:ALAssetsGroupPropertyName]]==NSOrderedSame) {
                                
                                //target album is found
                                albumWasFound = YES;
                                
                                //get a hold of the photo's asset instance
                                [self assetForURL: assetURL 
                                      resultBlock:^(ALAsset *asset) {
                                                  
                                          //add photo to the target album
                                          [group addAsset: asset];
                                          
                                          //run the completion block
                                          completionBlock(assetURL, nil);
                                          
                                      } failureBlock:^(NSError *error){
                                          completionBlock(nil, error);
                                      }];

                                //album was found, bail out of the method
                                return;
                            }
                            
                            if (group==nil && albumWasFound==NO) {
                                //photo albums are over, target album does not exist, thus create it
                                
                                __unsafe_unretained ALAssetsLibrary* weakSelf = self;

                                //create new assets album
                                [self addAssetsGroupAlbumWithName:albumName 
                                                      resultBlock:^(ALAssetsGroup *group) {
                                                                  
                                                          //get the photo's instance
                                                          [weakSelf assetForURL: assetURL 
                                                                        resultBlock:^(ALAsset *asset) {

                                                                            //add photo to the newly created album
                                                                            [group addAsset: asset];
                                                                            
                                                                            //call the completion block
                                                                            completionBlock(assetURL, nil);

                                                                        } failureBlock:^(NSError *error) {
                                                                            completionBlock(nil, error);
                                                                        }];
                                                          
                                                      } failureBlock:^(NSError *error){
                                                          completionBlock(nil, error);
                                                      }];

                                //should be the last iteration anyway, but just in case
                                return;
                            }
                            
                        } failureBlock:^(NSError *error){
                            completionBlock(nil, error);
                        }];
}

@end
